package com.tcl.aota.manage.imp;

import com.tcl.aota.common.constants.Constants;
import com.tcl.aota.common.utils.DateUtil;
import com.tcl.aota.common.utils.StringUtil;
import com.tcl.aota.manage.AppLogManage;
import com.tcl.aota.persistent.dao.db.AppDAO;
import com.tcl.aota.persistent.dao.db.AppLogDAO;
import com.tcl.aota.persistent.model.AppLog;
import org.perf4j.aop.Profiled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("appLogManage")
public class AppLogManageImp implements AppLogManage {

    private AppLogDAO appLogDAO;

    @Resource(name = "appLogDAO")
    public void setAppLogDAO(AppLogDAO appLogDAO) {
        this.appLogDAO = appLogDAO;
    }

    @Resource(name = "appDAO")
    private AppDAO appDAO;

    @Override
    @Profiled
    public int batchInsert(List<AppLog> appLogs) throws Exception {
        int result = 0;
        if (appLogs != null && appLogs.size() > 0) {
            result = appLogDAO.insertBath(appLogs);
        }
        return result;
    }


    @Override
    @Profiled
    public Map<String, Object> getAll() {
        Map<String, Object> map = new HashMap<>();
        map.put("hours", statisticsSplit(Constants.Common.STAT_HOUR, Constants.Common.DAY, 3));
        map.put("days", statisticsSplit(Constants.Common.STAT_DAY, Constants.Common.WEEK, 1));
        map.put("weeks", statisticsSplit(Constants.Common.STAT_WEEK, Constants.Common.WEEK_FOUR, 7));
        map.put("months", statisticsSplit(Constants.Common.STAT_MONTH, Constants.Common.MONTH, 1));
        return map;
    }

    /**
     * build 统计查询条件
     *
     * @param type
     * @param start
     * @param end
     * @return
     */
    @Profiled
    private Map<String, Object> conditions(int type, int start, int end) {
        String startTime = "";
        String endTime = "";
        switch (type) {
            case Constants.Common.STAT_HOUR:
                startTime = DateUtil.getBeforeHoursFromYeserday(start);
                endTime = DateUtil.getBeforeHoursFromYeserday(end);
                break;
            case Constants.Common.STAT_DAY:
                startTime = DateUtil.getBeforeDaysFromLastWeek(start);
                endTime = DateUtil.getBeforeDaysFromLastWeek(end);
                break;
            case Constants.Common.STAT_WEEK:
                startTime = DateUtil.getBeforeDaysFromLastWeek(start);
                endTime = DateUtil.getBeforeDaysFromLastWeek(end);
                break;
            case Constants.Common.STAT_MONTH:
                startTime = DateUtil.getBeforeMonthsFromLastMonth(start);
                endTime = DateUtil.getBeforeMonthsFromLastMonth(end);
                break;
        }
        Map<String, Object> conditions = new HashMap<>();
        conditions.put("start", startTime);
        conditions.put("end", endTime);
        return conditions;
    }

    @Profiled
    private boolean calculate(float dividend, float divisor, float percent) {
        return ((dividend / divisor) * 100.0F) >= percent;
    }

    @Profiled
    private AppLog binarySearch(List<AppLog> logs, long appId) {
        int low = 0, high = logs.size() - 1, mid;
        AppLog log = null;
        while (low <= high) {
            mid = (high + low) / 2;
            if (appId == logs.get(mid).getAppId()) {
                log = logs.get(mid);
                break;
            } else if (appId > logs.get(mid).getAppId()) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return log;
    }


    /**
     * 返回各个统计类型的下载量，安装量，更新量
     *
     * @param type：24小时,7天,4周,3个月
     * @param start：开始
     * @param step:间隔步长
     * @return
     */
    private Map<String, Object> statisticsSplit(int type, int start, int step) {
        int size = start / step;
        int[] download = new int[size];
        int[] install = new int[size];
        int[] upgrade = new int[size];
        int end = 0, i = 0;
        do {
            end = start - step;
            Map<String, Object> paramMap = conditions(type, start, end);
            List<Map<String, Object>> list = appLogDAO.selectGroupByStatusBetweenDate(paramMap);
            int[] group = getGroupCount(list);
            download[i] = group[0] + group[1] + group[2];
            install[i] = group[1] + group[2];
            upgrade[i] = group[2];
            start = end;
            i++;
        } while (end != 0);
        Map<String, Object> map = new HashMap<>();
        map.put(Constants.Common.DOWNLOAD, download);
        map.put(Constants.Common.INSTALL, install);
        map.put(Constants.Common.UPGRADE, upgrade);
        return map;
    }


    /**
     * 按status分解group结果为数组
     *
     * @param groupList
     * @return
     */
    private int[] getGroupCount(List<Map<String, Object>> groupList) {
        int[] group = new int[3];
        for (Map<String, Object> data : groupList) {
            int status = StringUtil.obj2int(data.get("status"));
            switch (status) {
                case 1:
                    group[0] = StringUtil.obj2int(data.get("total"));
                    break;
                case 2:
                    group[1] = StringUtil.obj2int(data.get("total"));
                    break;
                case 3:
                    group[2] = StringUtil.obj2int(data.get("total"));
                    break;
                default:
                    break;
            }
        }
        return group;
    }

    @Override
    public List<Map<String, Object>> selectAppGroupByAppIdBetweenDate(Map<String, Object> conditions) {
        List<Map<String, Object>> data = appLogDAO.selectAppGroupByAppIdBetweenDate(conditions);
        return convertDataMap(data);
    }

    @Override
    public int countAppGroupByAppIdBetweenDate(Map<String, Object> conditions) {
        return appLogDAO.countAppGroupByAppIdBetweenDate(conditions);
    }

    @Override
    public List<Map<String, Object>> selectAppGroupByDateBetweenDate(Map<String, Object> conditions) {
        List<Map<String, Object>> data = appLogDAO.selectAppGroupByDateBetweenDate(conditions);
        return convertDataMap(data);
    }

    @Override
    public int countAppGroupByDateBetweenDate(Map<String, Object> conditions) {
        return appLogDAO.countAppGroupByDateBetweenDate(conditions);
    }

    /**
     * 处理分组后的数据
     *
     * @param data
     * @return
     */
    private List<Map<String, Object>> convertDataMap(List<Map<String, Object>> data) {
        if (data == null) {
            return null;
        }
        for (Map<String, Object> dataMap : data) {
            int download = StringUtil.obj2int(dataMap.get("download"));
            int install = StringUtil.obj2int(dataMap.get("install"));
            int upgrade = StringUtil.obj2int(dataMap.get("upgrade"));
            dataMap.put("download", download + install + upgrade);
            dataMap.put("install", install + upgrade);
        }
        return data;
    }

    @Override
    public List<Map<String, Object>> selectAppImeiNumGroupByDate(Map<String, Object> condition) {
        return appLogDAO.selectAppImeiNumGroupByDate(condition);
    }

    @Override
    public int countAppImeiNumGroupByDate(Map<String, Object> conition) {
        return appLogDAO.countAppImeiNumGroupByDate(conition);
    }
}
